#ifndef TAPI32U8_H
#define TAPI32U8_H

#include <Windows.h>
#include "tapi32ex.h"
#include "tmisc.h"

#define MAX_PATH_U8		(MAX_PATH * 3)

struct WIN32_FIND_DATA_U8 
{
	DWORD		dwFileAttributes;
	FILETIME	ftCreationTime;
	FILETIME	ftLastAccessTime;
	FILETIME	ftLastWriteTime;
	DWORD		nFileSizeHigh;
	DWORD		nFileSizeLow;
	DWORD		dwReserved0;
	DWORD		dwReserved1;
	char		cFileName[ MAX_PATH_U8 ];
	char		cAlternateFileName[ 14 * 3 ];
};

// UTF8 string class
enum StrMode { BY_UTF8, BY_MBCS };

inline int WtoU8( const WCHAR* src, char* dst, int bufsize, int max_len=-1) {
	return	::WideCharToMultiByte( CP_UTF8, 0, src, max_len, dst, bufsize, 0, 0 );
}
inline int U8toW( const char* src, WCHAR* dst, int bufsize, int max_len=-1) {
	return	::MultiByteToWideChar( CP_UTF8, 0, src, max_len, dst, bufsize );
}
inline int WtoS( LPCWSTR src, char* dst, int bufsize, StrMode mode, int max_len=-1) {
	return ( mode == BY_UTF8) ? WtoU8( src, dst, bufsize, max_len)
		: WtoA( src, dst, bufsize, max_len );
}

WCHAR* U8toW( const char* src, bool noStatic = false );
char* WtoU8( const WCHAR* src, bool noStatic = false );
char* WtoA( const WCHAR* src, bool noStatic = false );
char* AtoU8( const char* src, bool noStatic = false );
char* U8toA( const char* src, bool noStatic = false );
char* toA( const void* src, bool noStatic = false );
WCHAR* toW( const void* src, bool noStatic = false );
void* toV( const char* src, bool noStatic = false );
void* toV( const WCHAR* src, bool noStatic = false );

class U8Str
{
public:
	U8Str( const WCHAR* s = NULL ){ _s = s ? WtoU8( s, true ) : NULL; }
	U8Str( const char* s, StrMode mode = BY_UTF8 )
	{
		_s = s ? mode == BY_UTF8 ? strdupNew( s ) : AtoU8( s, true ) : NULL;
	}
	U8Str( int len ) { if( len ){ _s = new char[len]; *_s = 0; } else { _s = NULL; } }
	~U8Str(){ delete[] _s; }
	operator const char*(){ return _s; }
	char* Buf(){ return _s; }
private:
	char* _s;
};

class Wstr 
{
public:
	Wstr(const char* _s, StrMode mode=BY_UTF8) 
	{
		s = _s ? mode == BY_UTF8 ? U8toW(_s, TRUE) : AtoW(_s, TRUE) : NULL;
	}
	Wstr(int len) { if (len) { s = new WCHAR [len]; *s = 0; } else { s = NULL; } }
	~Wstr() { delete [] s; }
	operator const WCHAR* () { return s; }
	operator const void* () { return s; }	// for V()
	WCHAR	*Buf() { return s; }

private:
	WCHAR* s;
};

class MBCSstr 
{
private:
	char	*s;
public:
	MBCSstr(const WCHAR *_s=NULL) { s = _s ? WtoA(_s, TRUE) : NULL; }
	MBCSstr(const char *_s, StrMode mode=BY_UTF8) {
		s = _s ? mode == BY_UTF8 ? U8toA(_s, TRUE) : strdupNew(s) : NULL;
	}
	MBCSstr(int len) { if (len) { s = new char [len]; *s = 0; } else { s = NULL; } }
	~MBCSstr() { delete [] s; }
	operator const char *() { return s; }
	char	*Buf() { return s; }
};

bool IsUTF8( const char* s );

HWND CreateWindowU8( const char* class_name, const char* window_name, DWORD style,
					int x, int y, int width, int height, HWND hParent, HMENU hMenu, HINSTANCE hInst, void* param );
HWND FindWindowU8( const char* class_name, const char* window_name = NULL );
BOOL AppendMenuU8( HMENU hMenu, UINT flags, UINT idItem, const char* item_str);
BOOL InsertMenuU8( HMENU hMenu, UINT idItem, UINT flags, UINT idNewItem, const char* item_str );
BOOL ModifyMenuU8( HMENU hMenu, UINT idItem, UINT flags, UINT idNewItem, const char* item_str );
DWORD GetFileAttributesU8( const char* path );
BOOL SetFileAttributesU8( const char* path, DWORD attr );

UINT DragQueryFileU8( HDROP hDrop, UINT iFile, char* buf, UINT cb );
void WIN32_FIND_DATA_WtoU8( const WIN32_FIND_DATAW *fdat_w, WIN32_FIND_DATA_U8 *fdat_u8,
						   BOOL include_fname=TRUE );
HANDLE FindFirstFileU8( const char* path, WIN32_FIND_DATA_U8 *fdat );
BOOL FindNextFileU8( HANDLE hDir, WIN32_FIND_DATA_U8 *fdat );
DWORD GetFullPathNameU8( const char* path, DWORD size, char* buf, char* *fname );
HANDLE CreateFileU8( const char* path, DWORD access_flg, DWORD share_flg,
					SECURITY_ATTRIBUTES *sa, DWORD create_flg, DWORD attr_flg, HANDLE hTemplate );
BOOL CreateDirectoryU8( const char* path, SECURITY_ATTRIBUTES *lsa );
BOOL DeleteFileU8( const char* path );
BOOL RemoveDirectoryU8( const char* path );

HINSTANCE ShellExecuteU8( HWND hWnd, LPCSTR op, LPCSTR file, LPSTR params, LPCSTR dir, int nShow );
BOOL ShellExecuteExU8( SHELLEXECUTEINFO *info );
DWORD GetCurrentDirectoryU8( DWORD size, char* dir );
DWORD GetWindowsDirectoryU8( char* dir, DWORD size );
BOOL SetCurrentDirectoryU8( char* dir );
BOOL GetOpenFileNameU8( LPOPENFILENAME ofn );
BOOL GetSaveFileNameU8( LPOPENFILENAME ofn );
BOOL ReadLinkU8( LPCSTR src, LPSTR dest, LPSTR arg );

LPSTR GetLoadStrU8( UINT resId, HINSTANCE hI = NULL );

#endif